#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN WEB SERVER

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For use in commercial software, please obtain a commercial license from THN Solutions LLC.    

  + For use in free software, this library is licensed under GPL version 3. A summary of 
	GPLv3 is listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt 
	included with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Record of Change
//             							CHANGE HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | DEVELOPER  | DESCRIPTION                                              |
// -------------------------------------------------------------------------------------
// | 13-Apr-13 | HaiNM      | First creation.                                          |
// -------------------------------------------------------------------------------------
//
#endregion

#region Record of Audit
//             							REVIEW HISTORY
// -------------------------------------------------------------------------------------
// |   DATE    | REVIEWER   | NOTES                                                    |
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
//
#endregion

#region Using directives
using System;

using Thn;
using Thn.Net;
using Thn.Net.Http;
using Thn.Collections;
#endregion

namespace Thn.Web
{
    /// <summary>
    /// This web server extends <see cref="SimpleHttpServer"/> to provide
    /// </summary>
#if DEBUG || TESTING
    public
#else
    public
#endif
 class WebServer : SimpleHttpServer
    {
        #region Fields
        bool mIsInitialized = false;
        protected UriToLocalPathTranslator mPathTranslator;
        protected IFileService mFileService;
        protected IMimeTypes mMimeTypes;

        #endregion

        #region Properties

        #region Root
        private string mRoot;
        /// <summary>
        /// Gets or sets root path.
        /// </summary>
        public string Root
        {
            get { return mRoot; }
            set
            {
                mRoot = value;
                if (mPathTranslator != null)
                {
                    mPathTranslator.Root = value;
                }
            }
        }
        #endregion

        #region Modules
        private List<IWebServerModule> mModules = new List<IWebServerModule>();
        /// <summary>
        /// Gets or sets list of modules.
        /// </summary>
        public List<IWebServerModule> Modules
        {
            get { return mModules; }
            set { mModules = value; }
        }
        #endregion
        
        #endregion

        #region On Start
        protected override void OnStart(ActionCallback callback)
        {
            if (!mIsInitialized)
            {
                OnInitialize();
                mIsInitialized = true;
            }
            base.OnStart(callback);
        }
        #endregion

        #region Initialize Modules
        void InitializeAllModules()
        {
            foreach (var item in mModules)
            {
                item.Initialize(this);
            }
        }
        #endregion

        #region On Initialize
        /// <summary>
        /// This method is called the first time this server starts.
        /// </summary>
        protected virtual void OnInitialize()
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(mRoot)) throw new Exception("Please assign a value to Root path");
            #endregion

            //mime types
            mMimeTypes = new MimeTypes();

            //path translator
            UriToLocalPathTranslator translator = new UriToLocalPathTranslator();
            translator.Root = mRoot;
            mPathTranslator = translator;

            //file service to handle file management
            DirectFileService fs = new DirectFileService();
            mFileService = fs;

            //register a request handler to serve up files.
            this.RequestHandlers.Add(new GenericFileRequestHandler()
                {
                    PathTranslator = mPathTranslator,
                    FileService = fs,
                    MimeTypes = mMimeTypes
                });

            ////router based on file extension
            //ExtensionRequestRouter router = new ExtensionRequestRouter();
            ////router.AddHandler(".mp4");
            //this.RequestHandlers.Add(new ExtensionRequestRouter()
            //{
            //});

#if DEBUG
            /*
             * In debug mode, this server will allow directory browsing.
             */
            //directory handler (return list of directories and files)
            this.RequestHandlers.Add(new DirectoryRequestHandler()
            {
                PathTranslator = mPathTranslator,
                FileService = mFileService,
                MimeTypes = mMimeTypes
            });
#else
            /*
             * In release mode, directory browsing might not be desirable
             * due to security reasons. Thus, we will replace the directory handler
             * as with a default index file instead.
             */

            //default index file handler
            this.RequestHandlers.Add(new DefaultFileHandler()
            {
                PathTranslator = mPathTranslator,
                FileService = mFileService,
            });

#endif

            InitializeAllModules();
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Create a new instance.
        /// </summary>
        public WebServer()
            : base()
        {
            mServerSignature = "THN Web Server";
        }
        #endregion
    }
}
